package com.gp.config;

import com.gp.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 来一杯凉咖
 * @create 2022/3/10 15:32
 */
@Configuration
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    //设置Token的你的存放方式
    @Bean
    public TokenStore tokenStore(){
        JwtTokenStore jwtTokenStore=new JwtTokenStore(jwtAccessTokenConverter()); //参数表示：谁生成的token
        return jwtTokenStore;
    }
    //获取token的生成器.
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){ //默认会把第三方的账号 和 范围  以及自己的账号和权限生成进去。
        JwtAccessTokenConverter jwtAccessTokenConverter=new JwtAccessTokenConverter(){
            @Override //扩展token的信息。
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

                User principal = (User) authentication.getPrincipal();//得到当前登录者的用户信息
                Map<String,Object> map=new HashMap<>();
                map.put("userid",principal.getUserId());
                ( (DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(map);
                OAuth2AccessToken enhancedToken = super.enhance(accessToken, authentication);
                return enhancedToken;
            }
        };
        jwtAccessTokenConverter.setSigningKey("123456");//token 密钥 不能外传
        return jwtAccessTokenConverter;
    }
    //用来绑定第三方应用的账号
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("qq") //随便起
                .secret(passwordEncoder.encode("123456"))  //第三方的密码 必须加密
                //授权的方式: 4种。
                //authorization_code" code码授权 最安全的。大企业都是实在这种方式进行授权。 支持外网和域名。
                // , "password", 密码授权方式: 需要你输入账号和密码。中小企业使用多。
                // "client_credentials", 客户端授权。
                // "implicit" 静默授权。
                .authorizedGrantTypes("password")
                .scopes("携带信息，自定义") //可以随便起 意义
                .accessTokenValiditySeconds(86400);//token的有效期 24*3600
    }

    @Autowired
    private AuthenticationManager authenticationManager;
    //设置oauth2暴露上面的token存放方式 和 token生成方式  认证方式
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                .accessTokenConverter(jwtAccessTokenConverter())
                .authenticationManager(authenticationManager);
    }
}
